package com.atguigu.ssyx.activity.service.impl;

import com.atguigu.ssyx.activity.mapper.CouponInfoMapper;
import com.atguigu.ssyx.activity.mapper.CouponRangeMapper;
import com.atguigu.ssyx.activity.mapper.CouponUseMapper;
import com.atguigu.ssyx.activity.service.ICouponInfoService;
import com.atguigu.ssyx.client.prouduct.ProductFeignClient;
import com.atguigu.ssyx.enums.CouponRangeType;
import com.atguigu.ssyx.model.activity.CouponInfo;
import com.atguigu.ssyx.model.activity.CouponRange;
import com.atguigu.ssyx.model.order.CartInfo;
import com.atguigu.ssyx.model.product.Category;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.atguigu.ssyx.vo.activity.CouponRuleVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 优惠券信息 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-06-30
 */
@Service
public class CouponInfoServiceImpl extends ServiceImpl<CouponInfoMapper, CouponInfo> implements ICouponInfoService {

    @Autowired
    private CouponInfoMapper couponInfoMapper;

    @Autowired
    private CouponRangeMapper couponRangeMapper;

    @Autowired
    private CouponUseMapper couponUseMapper;

    @Autowired
    private ProductFeignClient productFeignClient;

    @Override
    public IPage<CouponInfo> selectPage(Page<CouponInfo> pageParam) {
        //  构造排序条件
        QueryWrapper<CouponInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("id");
        IPage<CouponInfo> page = couponInfoMapper.selectPage(pageParam, queryWrapper);
        page.getRecords().stream().forEach(item -> {
//            根据枚举类设置优惠券类型。
            item.setCouponTypeString(item.getCouponType().getComment());
//设置优惠券范围。
            if (null != item.getRangeType()) {
                item.setRangeTypeString(item.getRangeType().getComment());
            }
        });
        //  返回数据集合
        return page;
    }

    @Override
    public Map<String, Object> findCouponRuleList(Long couponId) {
        Map<String, Object> result = new HashMap<>();
        CouponInfo couponInfo = this.getById(couponId);

        QueryWrapper couponRangeQueryWrapper = new QueryWrapper<CouponRange>();
        couponRangeQueryWrapper.eq("coupon_id", couponId);
        List<CouponRange> activitySkuList = couponRangeMapper.selectList(couponRangeQueryWrapper);

        List<Long> rangeIdList = activitySkuList.stream().map(CouponRange::getRangeId).collect(Collectors.toList());

        if (!CollectionUtils.isEmpty(rangeIdList)) {
            if (couponInfo.getRangeType() == CouponRangeType.SKU) {
                List<SkuInfo> skuInfoList = productFeignClient.findsSkuInfoList(rangeIdList);
                result.put("skuInfoList", skuInfoList);

            } else if (couponInfo.getRangeType() == CouponRangeType.CATEGORY) {
                List<Category> categoryList = productFeignClient.findCategoryList(rangeIdList);
                result.put("categoryList", categoryList);
            } else {
                //通用
            }
        }
        return result;
//      couponRule 是优惠信息，之后拿到couponrule的


//        couponrule的type是一个商品类型，那么range_ID是商品，type是一个分类类型，那么range_Id是一个分类。

//        可以有多个分类和多个商品。

    }

    @Override
    public void saveCouponRule(CouponRuleVo couponRuleVo) {
         /*
        优惠券couponInfo 与 couponRange 要一起操作：先删除couponRange ，更新couponInfo ，再新增couponRange ！
         */
        QueryWrapper<CouponRange> couponRangeQueryWrapper = new QueryWrapper<>();
        couponRangeQueryWrapper.eq("coupon_id", couponRuleVo.getCouponId());
        couponRangeMapper.delete(couponRangeQueryWrapper);

        //  更新数据
        CouponInfo couponInfo = this.getById(couponRuleVo.getCouponId());
        // couponInfo.setCouponType();
        couponInfo.setRangeType(couponRuleVo.getRangeType());
        couponInfo.setConditionAmount(couponRuleVo.getConditionAmount());
        couponInfo.setAmount(couponRuleVo.getAmount());
        couponInfo.setConditionAmount(couponRuleVo.getConditionAmount());
        couponInfo.setRangeDesc(couponRuleVo.getRangeDesc());

        couponInfoMapper.updateById(couponInfo);

        //  插入优惠券的规则 couponRangeList
        List<CouponRange> couponRangeList = couponRuleVo.getCouponRangeList();
        for (CouponRange couponRange : couponRangeList) {
            couponRange.setCouponId(couponRuleVo.getCouponId());
            //  插入数据
            couponRangeMapper.insert(couponRange);
        }
    }

    @Override
    public List<CouponInfo> findCouponInfoList(Long skuId, Long userId) {
//        远程调用product,获得skuId 的分类id:
        SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);

//      根据条件查询:skuId 分类id  userId.
//        通过skuid 找出通用和分类和对应skuid的券。
        List<CouponInfo> couponInfoList = baseMapper.selectCouponInfoList(skuInfo.getId(), skuInfo.getCategoryId(), userId);
        return couponInfoList;
    }

    @Override
    public List<CouponInfo> findCartCouponInfo(List<CartInfo> cartInfoList, Long userId) {
        /**
         * 1. 根据userId获得全部 的优惠券信息。
         * 而不是通过优惠券id查询，因为优惠券id可能不存在，但是优惠券信息是存在的。
         *  coupon_use   coupon_info  coupon_range  查询优惠券的优惠范围.
         */
        List<CouponInfo> userAllCouponInfoList = baseMapper.selectCartCouponInfoList(userId);

        if (CollectionUtils.isEmpty(userAllCouponInfoList)) return null;
//        2.返回list集合中,获得所有的优惠券id.
        List<Long> collect = userAllCouponInfoList.stream().map(CouponInfo::getId).collect(Collectors.toList());
        LambdaQueryWrapper<CouponRange> couponRangeQueryWrapper = new LambdaQueryWrapper<>();
//        id in ();
        couponRangeQueryWrapper.in(CouponRange::getCouponId, collect);
        List<CouponRange> couponRanges = couponRangeMapper.selectList(couponRangeQueryWrapper);
//        返回的数据是,一个优惠券id=1对应一个商品skuId=1,id=1,skuid是3,一个优惠券会有很多个skuId,一对多.
//        couponRanges.stream().
        Map<Long, List<Long>> cartInfocouponRanges = this.findCouponIdToSkuIdMap(cartInfoList, couponRanges);

// 3.获得优惠券的范围.coupon_range

        //优惠后减少金额
        BigDecimal reduceAmount = new BigDecimal("0");
        CouponInfo optimalCouponInfo = null;

//        临时获得计算最优优惠券.
        List<CouponInfo> couponInfoList = new ArrayList<>();
        for (CouponInfo couponInfo : userAllCouponInfoList) {
//            一张一张优惠券.
            if (CouponRangeType.ALL == couponInfo.getRangeType()) {
                //全场通用
                //判断是否满足优惠使用门槛
                //计算购物车商品的总价
                BigDecimal totalAmount = computeTotalAmount(cartInfoList);
                if (totalAmount.subtract(couponInfo.getConditionAmount()).doubleValue() >= 0) {
//                    优惠价格大于0
                    couponInfo.setIsSelect(1);
//                    满足   >= 0    条件进入优惠券列表
                    couponInfoList.add(couponInfo);
                }
            } else {
                //优惠券id对应的满足使用范围的购物项skuId列表
                List<Long> skuIdList = cartInfocouponRanges.get(couponInfo.getId());
//                cartInfoCouponList  购物车 里面可以使用优惠券的商品.
                List<CartInfo> cartInfoCouponList = cartInfoList.stream().filter(cartInfo -> skuIdList.contains(cartInfo.getSkuId())).collect(Collectors.toList());
                if (cartInfoCouponList == null) {
                    continue;
                }
                BigDecimal totalAmount = computeTotalAmount(cartInfoCouponList);
                if (totalAmount.subtract(couponInfo.getConditionAmount()).doubleValue() >= 0) {
                    couponInfo.setIsSelect(1);
//                    满足   >= 0    条件进入优惠券列表
                    couponInfoList.add(couponInfo);
                }
            }

//这张优惠券可以使用select=1可以使用,但是还要考虑优惠金额.


            Optional<CouponInfo> maxAmount = couponInfoList.stream().max(Comparator.comparing(CouponInfo::getAmount));
            maxAmount.ifPresent(item -> {
                if (item.getId() == couponInfo.getId()) {
                    couponInfo.setIsOptimal(1);
                }
            });


//            if (couponInfo.getIsSelect().intValue() == 1 && couponInfo.getAmount().subtract(reduceAmount).doubleValue() > 0) {
//
//
//            }

        }


//        if (null != optimalCouponInfo) {
//            optimalCouponInfo.setIsOptimal(1);
//        }

        return userAllCouponInfoList;
//  4. 获得优惠券id对应skuid列表.是一个map集合.


//        5.遍历全部集合,判断优惠券类型.是全场还是sku还是分类.

//        6. 返回List<CouponInfo> 集合.


    }

    //只有一张优惠券 couponId
    @Override
    public CouponInfo findCouponRuleLists(List<CartInfo> cartInfoList, Long couponId) {
        CouponInfo couponInfo = baseMapper.selectById(couponId);
        if (couponInfo == null) {
            return null;
        }
//        获得优惠规则
        List<CouponRange> couponRangeList = couponRangeMapper.selectList(new LambdaQueryWrapper<CouponRange>().eq(CouponRange::getCouponId, couponId));
//这个优惠券可以使用的商品skuId
        Map<Long, List<Long>> couponIdToSkuIdMap = this.findCouponIdToSkuIdMap(cartInfoList, couponRangeList);
//        获得优惠券id可以使用的skuId
        List<Long> value = couponIdToSkuIdMap.entrySet().iterator().next().getValue();
        couponInfo.setSkuIdList(value);

        return null;
    }

    private BigDecimal computeTotalAmount(List<CartInfo> cartInfoList) {
        BigDecimal total = new BigDecimal("0");
        for (CartInfo cartInfo : cartInfoList) {
            //是否选中
            if (cartInfo.getIsChecked().intValue() == 1) {
                BigDecimal itemTotal = cartInfo.getCartPrice().multiply(new BigDecimal(cartInfo.getSkuNum()));
                total = total.add(itemTotal);
            }
        }
        return total;
    }

    /**
     * 获取优惠券id对应的满足使用范围的购物项skuId列表
     * 说明：一个优惠券可能有多个购物项满足它的使用范围，那么多个购物项可以拼单使用这个优惠券
     *
     * @param cartInfoList
     * @param couponRangesList
     * @return
     */
    private Map<Long, List<Long>> findCouponIdToSkuIdMap(List<CartInfo> cartInfoList, List<CouponRange> couponRangesList) {
        Map<Long, List<Long>> couponIdToSkuIdMap = new HashMap<>();
//        根据优惠券id分组优惠券range信息.
        Map<Long, List<CouponRange>> couponRangeGroupList = couponRangesList.stream().collect(Collectors.groupingBy(CouponRange::getCouponId));
        Iterator<Map.Entry<Long, List<CouponRange>>> iterator = couponRangeGroupList.entrySet().iterator();
//        优惠券分组. value是优惠券的信息(类型和包含种类)
//        Map  优惠券id -- 优惠券list规则。
        while (iterator.hasNext()) {
            Map.Entry<Long, List<CouponRange>> entry = iterator.next();
//            相当于给mao一个迭代指针.
            Long couponId = entry.getKey();
            List<CouponRange> couponRangeList = entry.getValue();
//把有优惠券的加入集合.
            Set<Long> skuIdSet = new HashSet<>();
//            遍历每一个商品
            for (CartInfo cartInfo : cartInfoList) {
//                遍历每个优惠规则。
                for (CouponRange couponRange : couponRangeList) {
                    if (CouponRangeType.SKU == couponRange.getRangeType()
//                            优惠券是sku的
                            && couponRange.getRangeId().longValue() == cartInfo.getSkuId().intValue()) {
                        skuIdSet.add(cartInfo.getSkuId());
                    } else if (CouponRangeType.CATEGORY == couponRange.getRangeType() && couponRange.getRangeId().longValue() == cartInfo.getCategoryId().intValue()) {
//                        优惠券是分类券。
                        skuIdSet.add(cartInfo.getSkuId());
                    } else {

                    }
                }
            }
//            这是优惠券id对应的有优惠的skuId集合.
//            这个优惠券可以用在这些商品上.已经把没有的排除掉了.
            couponIdToSkuIdMap.put(couponId, new ArrayList<>(skuIdSet));
//           收集到了这张优惠券info可以用的商品.
        }
        return couponIdToSkuIdMap;
    }
}
